#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include"SList.h"
#include<stdlib.h>
#include<assert.h>
void SListPrint(SLTNode* plist)
{
	SLTNode* cur = plist;
	while (cur != NULL)
	{
		printf("%d-> ", cur->data);
		cur = cur->next;//走向下一个结点的地址
	}
	printf("NULL\n");
}
SLTNode* BuySLTNode(SLTDataType x)//定义一个新节点
{
	SLTNode* node = malloc(sizeof(SLTNode));
	node->data = x;
	node->next = NULL;
	return node;
}
void SListPushBack(SLTNode** pplist, SLTDataType x)//尾插
{
	SLTNode* newnode = BuySLTNode(x);
	//1.空
	//2.非空
	if (*pplist == NULL)
	{
		*pplist = newnode;
	}
	else
	{
		//找尾
		SLTNode* tail = *pplist;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}

}
void SListPushFront(SLTNode** pplist, SLTDataType x)//头插
{
	//不用考虑是不是空的问题，因为这里是创建第一个结点
	//用到二级指针，因为需要改变第一个节点的地址
	SLTNode* newnode = BuySLTNode(x);
	newnode->next = *pplist;
	*pplist = newnode;
}
void SListPopBack(SLTNode** pplist)//尾删
{
	//1.没有节点
	//2.一个节点
	//3.多个节点
	if (*pplist == NULL)//1.
	{
		return;
	}
	else if ((*pplist)->next == NULL)//2.
	{
		free(*pplist);
		*pplist = NULL;
	}
	else//3.
	{
		SLTNode* prev = NULL;
		SLTNode* tail = *pplist;
		while (tail->next != NULL)
		{
			prev = tail;
			tail = tail->next;
		}
		free(tail);
		prev->next = NULL;
	}
}
void SListPopFront(SLTNode** pplist)//头删
{
	if (*pplist == NULL)//1.
	{
		return;
	}
	else//2.3.剩一个节点不用特殊考虑！
	{
		SLTNode* next = (*pplist)->next;
		free(*pplist);
		*pplist = next;
	}
}

SLTNode* SListFind(SLTNode* plist, SLTDataType x)//查找
{
	SLTNode* cur = plist;
	while (cur != NULL)//while(cur),二者都可以
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}


//插入之前先查找pos，并在其后面插入
//pos找不到是给数的问题，人为因素，不去考虑
void SListInsertAfter(SLTNode* pos, SLTDataType x)//插入
{
	assert(pos);
	SLTNode* newnode = BuySLTNode(x);//创建一个新节点接上
	newnode->next = pos->next;//这两个不能颠倒顺序，一旦颠倒，则内存会被覆盖
	pos->next = newnode;
	//故，当在链表内部连接新的节点放入其中时，应在想象中先连接新创建的节点与它后面的节点
	// 再进行他前面的节点的next与此新节点的连接
	
	//避免被覆盖还有一种方式：如下(即再定义一个指针，进行赋值)
	//SLTNode* newnode=BuySLTNode(x);
	//SLTNode* next=pos->next;
	//newnode->next = next;
	//pos->next = newnode;
}

//相比较上一个，这个要多传一个参数，即起始链表的头结点
//根据头结点一点一点找到插入的上一个位置prev
//
// 需要考虑的是如果pos在第一个节点，则$处会崩，并且改变起始地址，用二级指针
// 用if判断
//
void SListInsertBefore(SLTNode** pplist, SLTNode* pos, SLTDataType x)//这种插入麻烦了，理解上一个即可，这种情况默认是在之前插入
{
	assert(pos);
	SLTNode* newnode = BuySLTNode(x);
	if (pos == *pplist)//头插
	{
		newnode->next = pos;
		*pplist = newnode;
	}
	else
	{
		SLTNode* prev = NULL;
		SLTNode* cur = *pplist;

		while (cur != pos)
		{
			prev = cur;//prev就是插入位置的上一个节点
			cur = cur->next;
		}

		prev->next = newnode;//
		newnode->next = pos;
	}
	
}
//先查pos
void SListEraseAfter(SLTNode* pos)//删除后节点//就不放在功能页了
{
	assert(pos);
	if (pos->next == NULL)
	{
		return;
	}
	else
	{
		SLTNode* next = pos->next;
		pos->next = next->next;
		free(next);
		next = NULL;//好习惯而已
	}
}
